package com.zhilianbao.leyaogo.http.callback;

import android.content.Context;

import com.bql.convenientlog.CLog;
import com.bql.utils.CheckUtils;
import com.bql.utils.EventManager;
import com.bql.utils.NumberUtlis;
import com.zhilianbao.leyaogo.R;
import com.zhilianbao.leyaogo.app.LeYaoGoApplication;
import com.zhilianbao.leyaogo.constants.HttpConfig;
import com.zhilianbao.leyaogo.events.UserEventCode;
import com.zhilianbao.leyaogo.http.convert.GsonConvert;
import com.zhilianbao.leyaogo.utils.Utils;
import com.zhilianbao.leyaogo.utils.XToastUtils;
import com.zhilianbao.okhttputils.OkHttpUtils;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONObject;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import okhttp3.Call;
import okhttp3.Response;

/**
 * ClassName: JsonCallback <br>
 * Description: 默认将返回的数据解析成需要的Bean,可以是 Bean，String，List，Map<br>
 * Author: Cyarie <br>
 * Created: 2016/7/7 16:43 <br>
 * Update Time：<br>
 * Update Description：<br>
 */
public abstract class JsonCallback<T> extends CommonCallback<T> {


    protected boolean isShowNetToast = true;//是否显示服务异常Toast通知 默认true

    private Context mContext;

    public JsonCallback(Context context, boolean isShowNetToast) {
        this(context);
        this.isShowNetToast = isShowNetToast;
    }

    public JsonCallback(Context context) {
        this.mContext = context;
    }

    @Override
    public T convertSuccess(Response response) throws Exception {
        //以下代码是通过泛型解析实际参数,泛型必须传
        Type genType = getClass().getGenericSuperclass();
        if (!(genType instanceof ParameterizedType))
            throw new IllegalStateException("Callback没有填写泛型参数");
        //从上述的类中取出真实的泛型参数，有些类可能有多个泛型，所以是数组
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        Type type = params[0];

        //Callback中的泛型类型 可能是Class 也有可能是带有泛型类型的泛型 例如 java.util.List<E>  分别做不同处理

        Type rawType;
        //Callback中的泛型为泛型类型
        if (type instanceof ParameterizedType) {
            //rawType的类型实际上是 Class，但 Class 实现了Type接口，所以我们用Type接收
            rawType = ((ParameterizedType) type).getRawType();
        }
        //Callback中的泛型为Class
        else {
            rawType = type;
        }


        //这里我们既然都已经拿到了泛型的真实类型，即对应的 class ，那么当然可以开始解析数据了，我们采用 Gson 解析
        //以下代码是根据泛型解析数据，返回对象，返回的对象自动以参数的形式传递到 onSuccess 中，可以直接使用
        String body = response.body().string();
        response.close();
        CLog.e("LogInterceptor", body);
        CLog.json("LogInterceptor", body);
        if (CheckUtils.isEmpty(body))
            return null;
        /**
         * 服务器返回的响应都包含success,errorMsg,errorCode，有些还包含returnValue部分
         */
        JSONObject jsonObject = new JSONObject(body);
        boolean success = jsonObject.optBoolean("success", true);
        final String msg = jsonObject.optString("errorMsg", "");
        int msgCode = jsonObject.optInt("errorCode", 0);
        String result = jsonObject.optString("returnValue", null);
        switch (msgCode) {
            case 0:
                /**
                 * msgCode = 0 代表成功，默认实现Gson解析成相应的实体Bean返回，可以自己替换成fastjson等
                 * 对于返回参数，先支持 String，然后优先支持class类型的字节码，最后支持type类型的参数
                 */
                if (success) {
                    //更新TokenId
                    if (result != null) {
                        updateTokenId(result);
                    }
                    if (rawType == String.class) {
                        return (T) result;
                    }
                    return GsonConvert.fromJson(result, type);
                } else {
                    OkHttpUtils.getInstance().getDelivery().post(() -> {
                        if (isShowNetToast)
                            //                            XTipsDialog.showFail(mContext, msg);
                            XToastUtils.showShortToast(msg);
                    });
                    CLog.e("LogInterceptor", "错误代码：" + msgCode + "，错误信息：" + msg);
                    throw new IllegalStateException(msgCode + "");
                }

                //不存在的用户
            case HttpConfig.MSG_CODE_412:
                CLog.e("LogInterceptor", "错误代码：" + msgCode + "，错误信息：" + msg);
                if (rawType == String.class)
                    return (T) (msgCode + "");
                break;

            //还未设置支付密码
            case HttpConfig.MSG_ERROR_CODE_10046:
                CLog.e("LogInterceptor", "错误代码：" + msgCode + "，错误信息：" + msg);
                if (rawType == String.class)
                    return (T) (msgCode + "");
                break;

            //用户已存在
            case HttpConfig.MSG_CODE_413:
                CLog.e("LogInterceptor", "错误代码：" + msgCode + "，错误信息：" + msg);
                if (rawType == String.class)
                    return (T) (msgCode + "");
                break;

            //插入数据库错误
            //            case 100:
            //                CLog.e("LogInterceptor", "错误代码：" + msgCode + "，错误信息：" + msg);
            //                throw new IllegalStateException(msgCode + "");
            //其他返回码抛出异常

            default:
                OkHttpUtils.getInstance().getDelivery().post(() -> {
                    if (isShowNetToast)
                        //                        XTipsDialog.showFail(mContext, msg);
                        XToastUtils.showShortToast(msg);
                });
                CLog.e("LogInterceptor", "错误代码：" + msgCode + "，错误信息：" + msg);
                throw new IllegalStateException(msgCode + "");
        }
        return null;

    }


    /**
     * 更新TokenId
     *
     * @param result
     */
    private void updateTokenId(String result) {
        try {
            JSONObject jsonObject = new JSONObject(result);
            if (jsonObject.has("tokenId")) {
                Utils.updateTokenId((String) jsonObject.get("tokenId"));
            }
        } catch (Exception e) {
            CLog.i("更新TokenId失败:返回值没有Token字段或者不是JsonObject类型" + "-----" + e.toString() + "-----" + result);
        }

    }

    @Override
    public void onError(Call call, Response response, Exception e) {
        super.onError(call, response, e);
        //        if (response == null)
        //            CLog.e("LogInterceptor", e.toString());
        //未连接网络 或者 服务器异常情况
        if (e != null && !CheckUtils.isEmpty(e.toString()))
            CLog.e("LogInterceptor", e.toString());

        if (response == null && isShowNetToast) {
            //            XTipsDialog.showFail(mContext, Utils.isNetConnected() ? LeYaoGoApplication.getContext().getString(R.string.server_error) : LeYaoGoApplication.getContext().getString(R.string.net_error));
            XToastUtils.showShortToast(Utils.isNetConnected() ? LeYaoGoApplication.getContext().getString(R.string.server_error) : LeYaoGoApplication.getContext().getString(R.string.net_error));
        }

        if (response != null && response.code() >= 400 && response.code() <= 599 && isShowNetToast) {
            //            XTipsDialog.showFail(mContext, LeYaoGoApplication.getContext().getString(R.string.server_error));
            XToastUtils.showShortToast(LeYaoGoApplication.getContext().getString(R.string.server_error));
            return;
        }
        //用户异常登录
        if (NumberUtlis.convertToint(e.getMessage(), 0) == HttpConfig.MSG_CODE_426) {
            EventBus.getDefault().post(new EventManager(UserEventCode.MSG_CODE_LOGIN_ERROR));
            EventBus.getDefault().post(new EventManager(UserEventCode.MSG_CODE_LOGIN_ERROR_TO_LOGIN_PAGE));
            Utils.clear();
            //            Utils.unregisterPush();
        }
        //数据库数据更新异常
        //        if (NumberUtlis.convertToint(e.getMessage(), 0) == 100 && isShowNetToast) {
        //            XTipsDialog.showFail(mContext, LeYaoGoApplication.getContext().getString(R.string.database_error));
        //            return;
        //        }
    }
}
